use fastrace::collector::Config;
use fastrace::collector::ConsoleReporter;
use log::LevelFilter;
use logforth::append::rolling_file::RollingFileBuilder;
use logforth::append::rolling_file::Rotation;
use logforth::layout::JsonLayout;
use logforth::layout::LogfmtLayout;
use poem::web::Json;
use poem::web::Path;
use poem::EndpointExt;
use serde::Deserialize;
use serde::Serialize;
use std::fs::File;

#[derive(Serialize, Deserialize, Debug)]
pub struct User {
    pub id: String,
    pub name: String,
    pub email: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct UserDetails {
    pub id: String,
    pub name: String,
    pub email: String,
}

#[poem::handler]
#[fastrace::trace] // Automatically creates and manages spans
async fn get_user(Path(user_id): Path<String>) -> Json<User> {
    log::info!("Fetching user {}", user_id);

    let user_details = fetch_user_details(&user_id).await;

    Json(User {
        id: user_id,
        name: user_details.name,
        email: user_details.email,
    })
}

#[fastrace::trace]
async fn fetch_user_details(user_id: &str) -> UserDetails {
    log::info!("fetch_user_details {}", user_id);

    UserDetails {
        id: "UserDetails ID".to_owned(),
        name: "UserDetails NAME".to_owned(),
        email: "UserDetails EMAIL".to_owned(),
    }
}

// cargo watch -i "logs/**" -x fmt -x "run --example fastrace_poem_demo" -c
#[tokio::main]
async fn main() {
    //setup_observability("user-service");

    let (rolling_writer, _guard) = RollingFileBuilder::new("logs")
        .layout(LogfmtLayout::default())
        .rotation(Rotation::Daily)
        .filename_prefix("app_log")
        .filename_suffix("log")
        .build()
        .unwrap();

    logforth::builder()
        .dispatch(|d| {
            d.filter(log::LevelFilter::Trace)
                .diagnostic(logforth::diagnostic::FastraceDiagnostic::default())
                .append(logforth::append::FastraceEvent::default())
                .append(rolling_writer)
        })
        .dispatch(|d| {
            d.filter(LevelFilter::Trace)
                .diagnostic(logforth::diagnostic::FastraceDiagnostic::default())
                .append(logforth::append::FastraceEvent::default())
                .append(logforth::append::Stdout::default())
        })
        .apply();

    //fastrace::set_reporter(ConsoleReporter, Config::default());

    log::info!("server start");

    let app = poem::Route::new()
        .at("/users/:id", poem::get(get_user))
        .with(fastrace_poem::FastraceMiddleware);

    poem::Server::new(poem::listener::TcpListener::bind("0.0.0.0:3000"))
        .run(app)
        .await
        .unwrap();

    fastrace::flush();
}

fn setup_observability(service_name: &str) {
    // let stderr_logger = logforth::stderr().dispatch(|d| {
    //     d.filter(log::LevelFilter::Trace)
    //         // Attaches trace id to logs
    //         .diagnostic(logforth::diagnostic::FastraceDiagnostic::default())
    //         // Attaches logs to spans
    //         .append(logforth::append::FastraceEvent::default())
    // });

    let (rolling_writer, _guard) = RollingFileBuilder::new("logs")
        .layout(JsonLayout::default())
        .rotation(Rotation::Daily)
        .filename_prefix("app_log")
        .build()
        .unwrap();

    logforth::builder()
        .dispatch(|d| d.filter(log::LevelFilter::Trace).append(rolling_writer))
        .dispatch(|d| {
            d.filter(LevelFilter::Trace)
                .diagnostic(logforth::diagnostic::FastraceDiagnostic::default())
                .append(logforth::append::FastraceEvent::default())
                .append(logforth::append::Stdout::default())
        })
        .apply();

    // fastrace::set_reporter(
    //     fastrace_jaeger::JaegerReporter::new("127.0.0.1:6831".parse().unwrap(), service_name)
    //         .unwrap(),
    //     fastrace::collector::Config::default(),
    // );
}
